package com.one.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.one.bean.*;
import com.one.config.WechatPayConfig;
import com.one.constant.RedisPrefixConstant;
import com.one.constant.WechatPayConstant;
import com.one.mapper.*;
import com.one.service.WechatPayService;
import com.one.service.WechatToolsService;
import com.one.util.HttpClient4Util;
import com.one.util.RedisUtils;
import com.one.util.WechatPayUtil;
import com.one.vo.UserVo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Create on 2022-01-19
 * <p>
 * Author: LiangWei
 * <p>
 * Description: 微信支付流程接口实现类
 **/
@Service
public class WechatPayServiceImpl implements WechatPayService {
    @Autowired(required = false)
    private WechatPayConfig wechatPayConfig;

    @Autowired
    private OrderMapper orderMapper;

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private WechatToolsService wechatToolsService;

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private TicketMapper ticketMapper;

    @Autowired
    private UserTicketMapper userTicketMapper;

    @Override
    public String wechatPayUnifiedOrderParamsXml(Integer userId,String token,String orderNo,Integer consigneeId,Integer totalFee,Integer ticketId) throws Exception {
        Map<String,String> paramMap = new HashMap<>();
        paramMap.put("appid",wechatPayConfig.getAppId());
        paramMap.put("mch_id",wechatPayConfig.getMchId());
        //设备号，PC网页或公众号内支付可以传"WEB"
        paramMap.put("device_info","WEB");
        //随机字符串，长度要求在32位以内，增加签名的安全性
        paramMap.put("nonce_str", WechatPayUtil.generateNonceStrUseRandom());
        //商品的简要描述
        paramMap.put("body","蘑菇街");
        //商户订单号
        paramMap.put("out_trade_no",orderNo);
        //附加信息
        paramMap.put("attach",wechatToolsService.createAttach(userId,token,consigneeId,ticketId));
        //标价金额

        paramMap.put("total_fee",totalFee.toString());
        //终端IP
        paramMap.put("spbill_create_ip","192.168.1.168");
        //通知回调地址，异步接收微信支付结果结果
        paramMap.put("notify_url",wechatPayConfig.getNotifyUrl());
        //交易类型
        paramMap.put("trade_type", WechatPayConstant.WECHAT_PAY_TRADE_TYPE_NATIVE);
        //商品ID，trade_type=NATIVE时，此参数必传
        paramMap.put("product_id",WechatPayUtil.generateNonceStrUseUUID(10));
        //签名，是使用上面所有参数进行签名，都是在参数确定最后，进行签名操作，自己不参与

        //需要传给微信官方，进行签名校验（微信官方会根据上面所有参数，重新签名，对比传递的sign值），防止接口交互不安全
        paramMap.put("sign",WechatPayUtil.generateSignature(paramMap,wechatPayConfig.getMchKey()));
        //将所有参数转换为xml字符串，返回
        return WechatPayUtil.generateMapToXml(paramMap);
    }

    @Override
    public Map<String, String> wechatPayUnifiedOrder(String unifiedOrderParamsXml) throws Exception {
        String unifiedOrderReturnXml = HttpClient4Util.getResponse4PostByString(wechatPayConfig.getOrderUrl(),unifiedOrderParamsXml,WechatPayConstant.WECHAT_PAY_ENCODING_UTF8);
        return WechatPayUtil.generateXmlToMap(unifiedOrderReturnXml);
    }

    @Override
    public String wechatPayUnifiedNotifyResole(String unifiedNotifyResultXml) throws Exception {
        // 将微信支付异步回调的xml字符串，转换为map
        Map<String,String> unifiedNotifyResultMap = WechatPayUtil.generateXmlToMap(unifiedNotifyResultXml);

        String cashFee = unifiedNotifyResultMap.get("cash_fee");
        BigDecimal price = new BigDecimal(cashFee);
        //实际价格
        BigDecimal truePrice = price.divide(new BigDecimal("100"));
        //交易号
        String transactionId = unifiedNotifyResultMap.get("transaction_id");
        //订单号（我放的订单编号）
        String outTradeNo = unifiedNotifyResultMap.get("out_trade_no");
        //附加信息
        String attach = unifiedNotifyResultMap.get("attach");

        //分解附加信息，获取用户id，token，consigneeId，ticketId
        String[] attachStr = attach.split(":");
        //用户id
        Integer userId = Integer.parseInt(attachStr[0]);
        //token
        String token = attachStr[1];
        //consigneeId
        Integer consigneeId = Integer.parseInt(attachStr[2]);
        //ticketId
        Integer ticketId = Integer.parseInt(attachStr[3]);


        // 只处理成功回调
        if(WechatPayConstant.WECHAT_PAY_RETURN_CODE_SUCCESS.equals(unifiedNotifyResultMap.get("return_code"))
                && WechatPayConstant.WECHAT_PAY_RESULT_CODE_SUCCESS.equals(unifiedNotifyResultMap.get("result_code"))){
            //签名校验
            if(WechatPayUtil.isSignatureValid(unifiedNotifyResultMap,wechatPayConfig.getMchKey())){
                //签名校验成功
                //TODO 进行业务
                //扫码支付成功，获取到回传的订单编号，操作数据库
                        //修改总订单
                BigDecimal zPrice = new BigDecimal(cashFee).divide(new BigDecimal("100"));
                OrderInfo orderInfo = new OrderInfo();
                    QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
                    wrapper.eq("order_no",outTradeNo);
                    orderInfo.setStatus(2);//该总订单状态
                    orderInfo.setPayNo(transactionId);//改总订单交易号
                    orderInfo.setPayDate(new Date());//改总订单交易时间
                    orderInfo.setTotalPrice(zPrice);//改总订单总金额
                    orderInfo.setAddress(consigneeId);//收货地址id
                    orderInfoMapper.update(orderInfo,wrapper);

                            //将每个从订单状态改为代发货
                    QueryWrapper<Orders> wrapper1 = new QueryWrapper<>();
                    wrapper1.eq("order_no",outTradeNo);
                    List<Orders> orders = orderMapper.selectList(wrapper1);
                    for(int i = 0;i<orders.size();i++) {
                        orders.get(i).setStatus(2);
                        orderMapper.updateById(orders.get(i));
                    }


                //order.setGetIntegral(Integer.valueOf(streetTicketFeignService.invokeUseFeignUpdateUserTicket(truePrice).getData()));
                    Integer integral = zPrice.intValue()/100*10;//用户积分

                    Integer integralSum = userMapper.selectById(userId).getIntegral()+integral;//用户积分总和

                    Object userObj = redisUtils.get(RedisPrefixConstant.LOGIN_TOKEN+token);
                    UserVo userVo = JSON.parseObject(userObj.toString(),UserVo.class);
                    userVo.setIntegral(integralSum);
                    //传入redis
                    redisUtils.set(RedisPrefixConstant.LOGIN_TOKEN,userVo);
                    //USER表存入总积分
                    User user = new User();
                    user.setId(userId);
                    user.setIntegral(integralSum);
                    userMapper.updateById(user);
                      //修改优惠券的状态（redis）
                if(ticketId!=0) {
                    String expiredKey = "user_ticket:" + userId;

                    List<Object> list = redisUtils.lGet(expiredKey, 0, -1);
                    List<JSONObject> couponList = list.stream().map(coupon -> JSON.parseObject(coupon.toString())).collect(Collectors.toList());
                    JSONObject t = couponList.get(ticketId);
                    if (t.getInteger("status") == 1) {
                        t.put("status", 0);
                        redisUtils.lUpdateIndex(expiredKey, ticketId, t);
                        redisUtils.del(expiredKey + ":" + ticketId);
                    }
                }
                return WechatPayConstant.WECHAT_PAY_NOTIFY_RESPONSE_SUCCESS;
            }
        }
        return WechatPayConstant.WECHAT_PAY_NOTIFY_RESPONSE_FAIL;
    }

    @Override
    public boolean judgeOrderWaitPay(String orderNo) {
        QueryWrapper<OrderInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no",orderNo);
        return orderInfoMapper.selectOne(wrapper).getStatus() == 1;
    }

    @Override
    public boolean judgeTicketFull(String orderNo, Integer ticketId) {
        Ticket ticket = ticketMapper.selectById(ticketId);
        BigDecimal leastPrice = new BigDecimal(0);
        if (!Objects.isNull(ticket)) {
            leastPrice=ticket.getLeastPrice();
        }
        BigDecimal price = new BigDecimal("0");
        QueryWrapper<Orders> wrapper = new QueryWrapper<>();
        wrapper.eq("order_no",orderNo);
        List<Orders> orders = orderMapper.selectList(wrapper);
        for(int i = 0;i<orders.size();i++){
            price = price.add(orders.get(i).getTotalPrice());
        }
        return price.compareTo(leastPrice)==1;
    }

    @Override
    public Integer getTruePrice(String orderNo,Integer ticketId) {
        BigDecimal totalPrice = new BigDecimal("0");
        QueryWrapper<Orders> wrapper = new QueryWrapper();
        wrapper.eq("order_no",orderNo);
        List<Orders> orders = orderMapper.selectList(wrapper);
        for(int i =0 ;i<orders.size();i++){
            totalPrice = totalPrice.add(orders.get(i).getTotalPrice());
        }
        if(ticketId!=0){
            totalPrice = totalPrice.subtract(ticketMapper.selectById(ticketId).getPrice());
        }
        QueryWrapper<OrderInfo> wrapper1 = new QueryWrapper<>();
        wrapper1.eq("order_no",orderNo);
        BigDecimal postage = orderInfoMapper.selectOne(wrapper1).getPostage();
        totalPrice = totalPrice.add(postage);
//        totalPrice = totalPrice.multiply(new BigDecimal("100"));
        String s = totalPrice.toString().replace(".","");
        Integer zPrice = Integer.parseInt(s);
        return zPrice;
    }


}
